home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / bix02.arc / PRINTER.PAS < prev    next >
Pascal/Delphi Source File  |  1986-08-04  |  6KB  |  198 lines

  1. {various parallel printer handling and error-checking}
  2. PROGRAM Printer;
  3.     {-demonstrate print error control}
  4.  
  5.     {***********************************************************************
  6.     the following can be included verbatim into a program}
  7.  
  8.   TYPE
  9.     Printers = (LPT1, LPT2, LPT3, LPT4, NoPrinter);
  10.   CONST
  11.     ActivePrinter : Printers = NoPrinter;
  12.   VAR
  13.     SavePrintTimeOut : Byte;
  14.     {
  15.     the following bytes normally equal $14, providing 20 retries on printer
  16.     busy calls. Set to 1 for a single retry (timeout takes about 2 seconds).
  17.     Do not set to 0 or system will retry forever.
  18.     }
  19.     PrintTimeOut : ARRAY[Printers] OF Byte ABSOLUTE $40 : $78;
  20.  
  21.  
  22.   PROCEDURE PrintChar(ch : Char);
  23.       {-print the character ch, handle errors and loop when busy}
  24.       {
  25.       **********************************************************************
  26.       CANNOT USE TURBO I/O FUNCTIONS INSIDE HERE DUE TO RE-ENTRANCY PROBLEMS
  27.       **********************************************************************
  28.       }
  29.  
  30.     TYPE
  31.       PrintErrors =
  32.       (TimeOut, unused1, unused2, IOerror, Selected,
  33.       OutOfPaper, Acknowledge, Busy, NoError);
  34.  
  35.       DisplayString = STRING[80];
  36.  
  37.       registers =
  38.       RECORD
  39.         CASE Integer OF
  40.           1 : (ax, bx, cx, dx, bp, si, di, ds, es, flags : Integer);
  41.           2 : (al, ah, bl, bh, cl, ch, dl, dh : Byte);
  42.       END;
  43.  
  44.     CONST
  45.       PrintErrorMsg : ARRAY[PrintErrors] OF DisplayString =
  46.       ('Printer Timeout Error', '', '', 'Printer Not Selected',
  47.       'Printer Not Selected', 'Printer Out of Paper',
  48.       'Printer Acknowledge Error', 'Printer Busy', '');
  49.  
  50.       EndStr : DisplayString = #13#10#36;
  51.  
  52.       {maximum number of replies with busy before calling it a timeout error.
  53.       may need to be adjusted empirically to avoid false timeouts}
  54.       BusyMax = 100;
  55.  
  56.     VAR
  57.       reg : registers;
  58.       Error : PrintErrors;
  59.       BusyCount : Integer;
  60.  
  61.     PROCEDURE writestring(s : DisplayString);
  62.         {-write string to standard output}
  63.       VAR
  64.         reg : registers;
  65.       BEGIN
  66.         reg.ah := 9;
  67.         reg.ds := Seg(s);
  68.         reg.dx := Ofs(s[1]);
  69.         MsDos(reg);
  70.       END;                    {displaystring}
  71.  
  72.     PROCEDURE getchar(VAR response : Char);
  73.         {-get a character from the keyboard}
  74.       VAR
  75.         reg : registers;
  76.       BEGIN
  77.         reg.ah := 0;
  78.         Intr($16, reg);
  79.         response := Chr(reg.al);
  80.       END;                    {getchar}
  81.  
  82.     FUNCTION AnyError(VAR Error : PrintErrors)
  83.         : Boolean;
  84.         {-check all the possible printer errors}
  85.         {-return TRUE and error if any found}
  86.  
  87.       FUNCTION SingleError(check : PrintErrors; VAR Error : PrintErrors)
  88.           : Boolean;
  89.           {-return true if specified error was found, setting error}
  90.         BEGIN
  91.           SingleError := ((1 SHL Ord(check)) AND reg.ah) <> 0;
  92.           Error := check;
  93.         END;                  {singleerror}
  94.  
  95.       BEGIN
  96.         AnyError := True;
  97.         IF SingleError(Busy, Error) THEN Exit;
  98.         IF SingleError(OutOfPaper, Error) THEN Exit;
  99.         IF SingleError(IOerror, Error) THEN Exit;
  100.         {polarity of "selected" flag is opposite of others}
  101.         IF NOT(SingleError(Selected, Error)) THEN Exit;
  102.         {made it through with no errors}
  103.         Error := NoError;
  104.         AnyError := False;
  105.       END;                    {anyerror}
  106.  
  107.     PROCEDURE HandleError(VAR Error : PrintErrors);
  108.         {-handle user-oriented error conditions}
  109.       VAR
  110.         response : Char;
  111.       BEGIN
  112.         IF (Error = NoError) THEN Exit;
  113.         IF (Error = Busy) THEN BEGIN
  114.           BusyCount := Succ(BusyCount);
  115.           IF BusyCount < BusyMax THEN Exit;
  116.           {busy too long, call it a timeout}
  117.           Error := TimeOut;
  118.         END;
  119.         {
  120.         prompt user to correct the error condition. screen handling could
  121.         be much fancier here but it cannot use Turbo I/O functions.
  122.         }
  123.         writestring(PrintErrorMsg[Error]+EndStr);
  124.         writestring('Correct condition and then press <ENTER> '+#36);
  125.         REPEAT
  126.           getchar(response);
  127.         UNTIL (response IN [#13, #3]);
  128.         writestring(EndStr);
  129.         IF response = #3 THEN Halt; {Ctrl-C}
  130.         BusyCount := 0;
  131.       END;                    {handleerror}
  132.  
  133.     BEGIN
  134.       IF ActivePrinter = NoPrinter THEN BEGIN
  135.         writestring('program error: no printer is selected'+EndStr);
  136.         Exit;
  137.       END;
  138.       reg.dx := Ord(ActivePrinter); {equals 0..3}
  139.       BusyCount := 0;
  140.  
  141.       REPEAT
  142.         {check printer status}
  143.         reg.ah := 2;
  144.         Intr($17, reg);
  145.  
  146.         {check for errors}
  147.         IF AnyError(Error) AND (Error <> Busy) THEN
  148.           HandleError(Error)
  149.         ELSE BEGIN
  150.           {print the character}
  151.           reg.ax := Ord(ch);
  152.           Intr($17, reg);
  153.           {check for errors again}
  154.           IF AnyError(Error) THEN
  155.             HandleError(Error);
  156.         END;
  157.       UNTIL Error = NoError;
  158.  
  159.     END;                      {printchar}
  160.  
  161.   PROCEDURE ProtectPrinter(Printer : Printers);
  162.       {-define the Lst device to print to the specified printer}
  163.     BEGIN
  164.       IF ActivePrinter = NoPrinter THEN BEGIN
  165.         ActivePrinter := Printer;
  166.         LstOutPtr := Ofs(PrintChar);
  167.         {save current printer timeout}
  168.         SavePrintTimeOut := PrintTimeOut[Printer];
  169.         {set to minimum timeout period}
  170.         PrintTimeOut[Printer] := 1;
  171.       END ELSE
  172.         WriteLn(Con,
  173.         'program error: only one printer can be protected at a time');
  174.     END;                      {protectprinter}
  175.  
  176.   PROCEDURE RestorePrinter;
  177.       {-deassign the Lst device and restore the printer timeout}
  178.     BEGIN
  179.       IF ActivePrinter <> NoPrinter THEN BEGIN
  180.         PrintTimeOut[ActivePrinter] := SavePrintTimeOut;
  181.         ActivePrinter := NoPrinter;
  182.       END;
  183.     END;                      {restoreprinter}
  184.  
  185.     {end of include portion
  186.     ***********************************************************************}
  187.  
  188.     {demonstration follows}
  189.   VAR
  190.     i : Integer;
  191.   BEGIN
  192.     ProtectPrinter(LPT1);
  193.     FOR i := 1 TO 5 DO
  194.       {any writes to the Lst device are now protected}
  195.       WriteLn(Lst, 'hello hello hello hello');
  196.     RestorePrinter;
  197.   END.
  198.